package block

import (
	"bytes"
	"encoding/gob"
	"publicChainSystemTest/pow"
	"publicChainSystemTest/tools"
	"publicChainSystemTest/transaction"
	"strconv"
	"time"
)

/**
 *@author:zhengyilong
 *@email:1797344574@qq.com
 *@phone:13479394730
 *@DateTime:2022/4/11 9:04
 **/

type Block struct {
	Timestamp int64
	//Data      []byte
	Txs []transaction.Transaction
	PrevHash  []byte
	Hash      []byte
	Nonce     int64
}

func (block *Block)GetTimestamp() int64 {
	return block.Timestamp
}
func (block *Block)GetTxs() []transaction.Transaction {
	return block.Txs
}
func (block *Block)GetPrevHash() []byte {
	return block.PrevHash
}

func (b *Block) SetHash()error {
	timestamp := []byte(strconv.FormatInt(b.Timestamp,10))

	txsBytes := []byte{}
	for _, value := range b.Txs {
		serialize, err := value.Serialize()
		if err != nil {
			return  err
		}
		txsBytes = append(txsBytes, serialize...)
	}

	join := bytes.Join([][]byte{timestamp, txsBytes, b.PrevHash}, []byte{})
	hash := tools.Sha256(join)
	b.Hash = hash[:]
	return nil
}

func NewBlock(Txs []transaction.Transaction,prevhash []byte)*Block  {
	b := Block{
		Timestamp: time.Now().Unix(),
		//Data:      data,
		Txs:Txs,
		PrevHash:  prevhash,
	}
	//block.SetHash()
	work := pow.NewProofOfWork(&b)
	hash, nonce := work.Run()
	b.Hash=hash
	b.Nonce =nonce

	return &b
}

func NewGenesisBlock(tx transaction.Transaction) *Block {
	return NewBlock([]transaction.Transaction{tx},nil)
}

/*
序列化	把目标结构体转成一个有序的序列
	json	xml
*/
func (block *Block) Serialize() ([]byte,error){
	var result bytes.Buffer
	en := gob.NewEncoder(&result)
	err := en.Encode(block)
	if err != nil {
		return nil,err
	}
	return result.Bytes(),nil
}

/*
反序列化		把字节切片转成结构体
*/
func DeSerialize(data []byte) (*Block,error){
	reader := bytes.NewReader(data)
	de := gob.NewDecoder(reader)
	var block *Block
	err := de.Decode(&block)
	if err != nil {
		return nil,err
	}
	return block,nil
}